# -*- coding: utf-8 -*-

# __date:       2021/6/18
# __author:     YangChao
# __function:

import os
import sys
import traceback

from PyQt5 import QtWidgets
from PyQt5.QtGui import QTextCursor
from PyQt5.QtCore import pyqtSlot, QObject, pyqtSignal
from PyQt5.QtWidgets import QApplication

from core.gui.ui_dialog import Ui_Dialog
from core.tool.utlis import qarange
from core.tool.parse_yaml import generate_yaml_doc, parse_yaml_args
from core.log import iqlog
from core.instrument.dc import DC
from core.instrument.dac import DAC
from core.instrument.spectrum_analyzer import SpectrumAnalyzer
from core.experiment.enumeration import EnumerationCalibration
from core.experiment.search import SearchCalibration


class ReadQss:

    @staticmethod
    def readQss(style: str = None):
        if not style:
            style = r'D:\work_loc\IQMixed\autocali\core\gui\style.qss'
        with open(style, 'r') as f:
            return f.read()


@pyqtSlot(str)
class Stream(QObject):
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))
        QApplication.processEvents()


@pyqtSlot(str)
class StreamError(QObject):
    newText = pyqtSignal(str)

    def write(self, text):
        self.newText.emit(str(text))
        QApplication.processEvents()


class QMyGui(Ui_Dialog):

    def band_func(self):
        # 绑定功能
        sys.stdout = Stream(newText=self.onUpdateText)
        sys.stderr = StreamError(newText=self.onUpdateText_err)
        self.pushButton_update.clicked.connect(self.update_param)
        self.pushButton1.clicked.connect(self.start_enumeration_test)
        self.pushButton2.clicked.connect(self.start_search_test)
        self.pushButton.clicked.connect(self.open_result_file)

    def start_enumeration_test(self):
        # 执行枚举校准流程
        try:
            # self.init_param()
            self.textEdit.clear()
            self.file = enumeration_calibration()
        except Exception as e:
            iqlog.error(traceback.print_exc())

    def start_search_test(self):
        # 执行搜索校准流程
        try:
            # self.init_param()
            self.textEdit.clear()
            self.file = search_calibration()
        except Exception as e:
            iqlog.error(traceback.print_exc())

    def open_result_file(self):
        # 打开结果文件位置
        try:
            os.startfile(self.file)
        except Exception:
            print('Sorry! You do not run any experiment!')

    def onUpdateText(self, text):
        """keyShow 是我自定义的TextEdit命名"""
        cursor = self.textEdit.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.textEdit.setTextCursor(cursor)
        self.textEdit.ensureCursorVisible()

    def onUpdateText_err(self, text):
        cursor = self.textEdit.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.textEdit.setTextCursor(cursor)
        self.textEdit.ensureCursorVisible()

    def init_param(self):
        # 从yaml中读取参数到Gui中
        data = parse_yaml_args()
        self.lineEdit_lo.setText(str(data["f_lo"]))
        self.lineEdit_init_amp.setText(str(data["init_amp"]))
        self.lineEdit_dc_min.setText(str(data["dc_min"]))
        self.lineEdit_dc_max.setText(str(data["dc_max"]))
        self.lineEdit_amp_min.setText(str(data["amp_min"]))
        self.lineEdit_amp_max.setText(str(data["amp_max"]))
        self.lineEdit_phase_min.setText(str(data["phase_min"]))
        self.lineEdit_phase_max.setText(str(data["phase_max"]))
        self.lineEdit_dc_scope1.setText(str(data["scope_list"][0]))
        self.lineEdit_amp_scope.setText(str(data["scope_list"][1]))
        self.lineEdit_phase_scope.setText(str(data["scope_list"][2]))
        self.lineEdit_dc_scope2.setText(str(data["scope_list"][3]))
        self.lineEdit_dc_step1.setText(str(data["step_list"][0]))
        self.lineEdit_amp_step.setText(str(data["step_list"][1]))
        self.lineEdit_phase_step.setText(str(data["step_list"][2]))
        self.lineEdit_dc_step2.setText(str(data["step_list"][3]))
        self.lineEdit_dc_search1.setText(str(data["dc_process"][0]))
        self.lineEdit_dc_search2.setText(str(data["dc_process"][1]))
        self.lineEdit_dc_search3.setText(str(data["dc_process"][2]))
        self.lineEdit_amp_search1.setText(str(data["amp_process"][0]))
        self.lineEdit_amp_search2.setText(str(data["amp_process"][1]))
        self.lineEdit_phase_search1.setText(str(data["phase_process"][0]))
        self.lineEdit_phase_search2.setText(str(data["phase_process"][1]))
        self.lineEdit_rf.setText(str(data["cur_rf"]))
        self.lineEdit_rf_left.setText(str(data["sweep_rf"][0]))
        self.lineEdit_rf_right.setText(str(data["sweep_rf"][1]))
        self.lineEdit_rf_step.setText(str(data["sweep_rf"][2]))
        self.checkBox.setCheckable(True)
        self.checkBox.setChecked(data["multiple_test"])

    def update_param(self):
        # 设置参数时执行,更新实验参数
        f_lo = float(self.lineEdit_lo.text())
        init_amp = float(self.lineEdit_init_amp.text())
        dc_min = float(self.lineEdit_dc_min.text())
        dc_max = float(self.lineEdit_dc_max.text())
        amp_min = float(self.lineEdit_amp_min.text())
        amp_max = float(self.lineEdit_amp_max.text())
        phase_min = float(self.lineEdit_phase_min.text())
        phase_max = float(self.lineEdit_phase_max.text())
        scope1 = float(self.lineEdit_dc_scope1.text())
        scope2 = float(self.lineEdit_amp_scope.text())
        scope3 = float(self.lineEdit_phase_scope.text())
        scope4 = float(self.lineEdit_dc_scope2.text())
        step1 = float(self.lineEdit_dc_step1.text())
        step2 = float(self.lineEdit_amp_step.text())
        step3 = float(self.lineEdit_phase_step.text())
        step4 = float(self.lineEdit_dc_step2.text())
        dc1 = float(self.lineEdit_dc_search1.text())
        dc2 = float(self.lineEdit_dc_search2.text())
        dc3 = float(self.lineEdit_dc_search3.text())
        amp1 = float(self.lineEdit_amp_search1.text())
        amp2 = float(self.lineEdit_amp_search2.text())
        phase1 = float(self.lineEdit_phase_search1.text())
        phase2 = float(self.lineEdit_phase_search2.text())
        rf_left = float(self.lineEdit_rf_left.text())
        rf_right = float(self.lineEdit_rf_right.text())
        rf_step = float(self.lineEdit_rf_step.text())
        f_rf = float(self.lineEdit_rf.text())
        multiple_test = self.checkBox.isChecked()
        data = {
            'f_lo': f_lo,
            'init_amp': init_amp,
            'dc_min': dc_min,
            'dc_max': dc_max,
            'amp_min': amp_min,
            'amp_max': amp_max,
            'phase_min': phase_min,
            'phase_max': phase_max,
            'scope_list': [scope1, scope2, scope3, scope4],
            'step_list': [step1, step2, step3, step4],
            'dc_process': [dc1, dc2, dc3],
            'amp_process': [amp1, amp2],
            'phase_process': [phase1, phase2],
            'cur_rf': f_rf,
            'sweep_rf': [rf_left, rf_right, rf_step],
            'multiple_test' : multiple_test
        }
        generate_yaml_doc(data)
        print("参数设置成功!")

    def readQss(self, style: str=None):
        if not style:
            style = './style.qss'
        with open(style, 'r') as f:
            return f.read()

    @staticmethod
    def run_gui():
        # 创建一个QApplication，也就是你要开发的软件app
        app = QtWidgets.QApplication(sys.argv)
        # 创建一个QMainWindow，用来装载你需要的各种组件、控件
        MainWindow = QtWidgets.QMainWindow()
        # ui是你创建的ui类的实例化对象
        ui = QMyGui()
        # 执行类中的setupUi方法，方法的参数是第二步中创建的QMainWindow
        ui.setupUi(MainWindow)
        # 初始化参数
        ui.init_param()
        # 板顶功能
        ui.band_func()
        # 设置qss样式
        qssStyle = ReadQss.readQss()
        MainWindow.setStyleSheet(qssStyle)
        # 执行QMainWindow的show()方法，显示这个QMainWindow
        MainWindow.show()
        sys.exit(app.exec_())


def enumeration_calibration():
    dc = DC()
    dac = DAC()
    analyzer = SpectrumAnalyzer()
    exp = EnumerationCalibration(dc, dac, analyzer)
    exp.run()
    return exp.file


def search_calibration():
    dc = DC()
    dac = DAC()
    analyzer = SpectrumAnalyzer()
    exp = SearchCalibration(dc, dac, analyzer)
    exp.run()
    return exp.file
